use crate::document::DocumentManager;
use codegraph_core::{GraphSystem, Parser, Result as CoreResult};
use codegraph_languages::LanguageRegistry;
use codegraph_parser::TreeSitterParser;
use tower_lsp::lsp_types::{Diagnostic, DiagnosticSeverity, Position, Range, Url, NumberOrString, DiagnosticTag};
use std::sync::Arc;
use std::collections::HashMap;
use std::time::{Duration, Instant};
use tokio::sync::{RwLock, Mutex};
use tower_lsp::Client;
use tracing::{debug, error, warn};
use regex::Regex;

/// Cache entry for diagnostic results
#[derive(Debug, Clone)]
struct DiagnosticsCacheEntry {
    diagnostics: Vec<Diagnostic>,
    timestamp: Instant,
    content_hash: u64,
}

/// Diagnostics cache with TTL
struct DiagnosticsCache {
    entries: HashMap<String, DiagnosticsCacheEntry>,
    ttl: Duration,
}

impl DiagnosticsCache {
    fn new(ttl: Duration) -> Self {
        Self {
            entries: HashMap::new(),
            ttl,
        }
    }

    fn get(&self, key: &str, content_hash: u64) -> Option<Vec<Diagnostic>> {
        if let Some(entry) = self.entries.get(key) {
            if entry.timestamp.elapsed() < self.ttl && entry.content_hash == content_hash {
                return Some(entry.diagnostics.clone());
            }
        }
        None
    }

    fn insert(&mut self, key: String, diagnostics: Vec<Diagnostic>, content_hash: u64) {
        let entry = DiagnosticsCacheEntry {
            diagnostics,
            timestamp: Instant::now(),
            content_hash,
        };
        self.entries.insert(key, entry);
    }

    fn clear(&mut self) {
        self.entries.clear();
    }
}

/// Enhanced diagnostics provider with intelligent error detection and caching
pub struct DiagnosticsProvider {
    client: Client,
    document_manager: Arc<DocumentManager>,
    graph_system: Arc<RwLock<Option<GraphSystem>>>,
    language_registry: LanguageRegistry,
    cache: Arc<Mutex<DiagnosticsCache>>,
    // Pre-compiled regex patterns for common errors
    error_patterns: HashMap<String, Vec<(Regex, DiagnosticSeverity, String)>>,
    // Debounce timer for real-time diagnostics
    debounce_timers: Arc<Mutex<HashMap<String, Instant>>>,
}

impl DiagnosticsProvider {
    pub fn new(
        client: Client,
        document_manager: Arc<DocumentManager>,
        graph_system: Arc<RwLock<Option<GraphSystem>>>,
    ) -> Self {
        let cache = Arc::new(Mutex::new(DiagnosticsCache::new(Duration::from_secs(30)))); // 30 second TTL
        let debounce_timers = Arc::new(Mutex::new(HashMap::new()));

        // Pre-compile error patterns for different languages
        let mut error_patterns = HashMap::new();

        // Python error patterns
        let mut python_patterns = Vec::new();
        python_patterns.push((
            Regex::new(r"^\s*def\s+\w+\([^)]*\)\s*$").unwrap(),
            DiagnosticSeverity::ERROR,
            "Function definition missing colon".to_string(),
        ));
        python_patterns.push((
            Regex::new(r"^\s*if\s+.*[^:]\s*$").unwrap(),
            DiagnosticSeverity::ERROR,
            "If statement missing colon".to_string(),
        ));
        python_patterns.push((
            Regex::new(r"^\s*for\s+.*[^:]\s*$").unwrap(),
            DiagnosticSeverity::ERROR,
            "For loop missing colon".to_string(),
        ));
        python_patterns.push((
            Regex::new(r"^\s*while\s+.*[^:]\s*$").unwrap(),
            DiagnosticSeverity::ERROR,
            "While loop missing colon".to_string(),
        ));
        python_patterns.push((
            Regex::new(r"\b(print|len|str|int|float|list|dict|set|tuple)\s*\(").unwrap(),
            DiagnosticSeverity::INFORMATION,
            "Built-in function usage".to_string(),
        ));
        error_patterns.insert("python".to_string(), python_patterns);

        // JavaScript/TypeScript error patterns
        let mut js_patterns = Vec::new();
        js_patterns.push((
            Regex::new(r"^\s*function\s+\w+\s*\([^)]*\)\s*$").unwrap(),
            DiagnosticSeverity::ERROR,
            "Function definition missing body".to_string(),
        ));
        js_patterns.push((
            Regex::new(r"^\s*if\s*\([^)]*\)\s*$").unwrap(),
            DiagnosticSeverity::ERROR,
            "If statement missing body".to_string(),
        ));
        js_patterns.push((
            Regex::new(r"console\.(log|error|warn|info)").unwrap(),
            DiagnosticSeverity::WARNING,
            "Console statement should be removed in production".to_string(),
        ));
        js_patterns.push((
            Regex::new(r"==\s*(?:null|undefined)").unwrap(),
            DiagnosticSeverity::WARNING,
            "Use strict equality (===) instead".to_string(),
        ));
        error_patterns.insert("javascript".to_string(), js_patterns.clone());
        error_patterns.insert("typescript".to_string(), js_patterns);

        // Rust error patterns
        let mut rust_patterns = Vec::new();
        rust_patterns.push((
            Regex::new(r"^\s*fn\s+\w+\s*\([^)]*\)\s*$").unwrap(),
            DiagnosticSeverity::ERROR,
            "Function definition missing body".to_string(),
        ));
        rust_patterns.push((
            Regex::new(r"println!\s*\(").unwrap(),
            DiagnosticSeverity::INFORMATION,
            "Debug print statement".to_string(),
        ));
        rust_patterns.push((
            Regex::new(r"unwrap\(\)").unwrap(),
            DiagnosticSeverity::WARNING,
            "Consider using proper error handling instead of unwrap()".to_string(),
        ));
        error_patterns.insert("rust".to_string(), rust_patterns);

        Self {
            client,
            document_manager,
            graph_system,
            language_registry: LanguageRegistry::new(),
            cache,
            error_patterns,
            debounce_timers,
        }
    }

    /// Update diagnostics with debouncing to avoid excessive computation
    pub async fn update_diagnostics(&self, uri: &Url) -> CoreResult<()> {
        debug!("Updating diagnostics for: {}", uri);

        // Implement debouncing to avoid excessive diagnostics updates
        let should_update = {
            let mut timers = self.debounce_timers.lock().await;
            let uri_str = uri.to_string();
            let now = Instant::now();

            if let Some(last_update) = timers.get(&uri_str) {
                if now.duration_since(*last_update) < Duration::from_millis(300) {
                    // Too soon, skip this update
                    false
                } else {
                    timers.insert(uri_str, now);
                    true
                }
            } else {
                timers.insert(uri_str, now);
                true
            }
        };

        if !should_update {
            debug!("Skipping diagnostics update due to debouncing: {}", uri);
            return Ok(());
        }

        let diagnostics = self.compute_diagnostics(uri).await?;

        self.client
            .publish_diagnostics(uri.clone(), diagnostics, None)
            .await;

        Ok(())
    }

    /// Update diagnostics immediately without debouncing (for explicit requests)
    pub async fn update_diagnostics_immediate(&self, uri: &Url) -> CoreResult<()> {
        debug!("Updating diagnostics immediately for: {}", uri);

        let diagnostics = self.compute_diagnostics(uri).await?;

        self.client
            .publish_diagnostics(uri.clone(), diagnostics, None)
            .await;

        Ok(())
    }

    async fn compute_diagnostics(&self, uri: &Url) -> CoreResult<Vec<Diagnostic>> {
        let start_time = Instant::now();

        // Get document content and language
        let (content, language, content_hash) = {
            let doc = self.document_manager.get_document(uri);
            match doc {
                Some(doc_ref) => {
                    let doc = doc_ref.read().await;
                    let content = doc.content.clone();
                    let content_hash = self.compute_content_hash(&content);
                    (content, doc.language.clone(), content_hash)
                }
                None => {
                    warn!("Document not found for diagnostics: {}", uri);
                    return Ok(Vec::new());
                }
            }
        };

        let language = match language {
            Some(lang) => lang,
            None => {
                debug!("No language detected for: {}", uri);
                return Ok(Vec::new());
            }
        };

        // Check cache first
        let cache_key = format!("{}:{}", uri, language);
        {
            let cache = self.cache.lock().await;
            if let Some(cached_diagnostics) = cache.get(&cache_key, content_hash) {
                debug!(
                    "Cache hit for diagnostics '{}' ({}ms)",
                    uri,
                    start_time.elapsed().as_millis()
                );
                return Ok(cached_diagnostics);
            }
        }

        let mut diagnostics = Vec::new();

        // Check for pattern-based errors first (fast)
        let pattern_diagnostics = self.check_pattern_errors(&content, &language);
        diagnostics.extend(pattern_diagnostics);

        // Parse the document and check for syntax errors
        if let Ok(parse_diagnostics) = self.check_syntax_errors(&content, &language).await {
            diagnostics.extend(parse_diagnostics);
        }

        // Check for semantic issues using the graph system
        if let Ok(semantic_diagnostics) = self.check_semantic_issues(&content, &language, uri).await {
            diagnostics.extend(semantic_diagnostics);
        }

        // Check for code quality issues
        if let Ok(quality_diagnostics) = self.check_code_quality(&content, &language).await {
            diagnostics.extend(quality_diagnostics);
        }

        // Remove duplicates and sort by severity
        diagnostics.sort_by(|a, b| {
            match (a.severity, b.severity) {
                (Some(sev_a), Some(sev_b)) => sev_a.cmp(&sev_b),
                (Some(_), None) => std::cmp::Ordering::Less,
                (None, Some(_)) => std::cmp::Ordering::Greater,
                (None, None) => std::cmp::Ordering::Equal,
            }
        });
        diagnostics.dedup_by(|a, b| a.range == b.range && a.message == b.message);

        // Cache the results
        {
            let mut cache = self.cache.lock().await;
            cache.insert(cache_key, diagnostics.clone(), content_hash);
        }

        let elapsed = start_time.elapsed();
        debug!(
            "Generated {} diagnostics for {} in {}ms",
            diagnostics.len(),
            uri,
            elapsed.as_millis()
        );

        Ok(diagnostics)
    }

    /// Compute a simple hash for content to use in caching
    fn compute_content_hash(&self, content: &str) -> u64 {
        use std::collections::hash_map::DefaultHasher;
        use std::hash::{Hash, Hasher};

        let mut hasher = DefaultHasher::new();
        content.hash(&mut hasher);
        hasher.finish()
    }

    /// Fast pattern-based error detection using pre-compiled regex
    fn check_pattern_errors(&self, content: &str, language: &str) -> Vec<Diagnostic> {
        let mut diagnostics = Vec::new();

        if let Some(patterns) = self.error_patterns.get(language) {
            for (line_num, line) in content.lines().enumerate() {
                for (pattern, severity, message) in patterns {
                    if pattern.is_match(line) {
                        let range = Range::new(
                            Position::new(line_num as u32, 0),
                            Position::new(line_num as u32, line.len() as u32),
                        );

                        let mut diagnostic = Diagnostic::new_simple(range, message.clone());
                        diagnostic.severity = Some(*severity);
                        diagnostic.source = Some("codegraph-pattern".to_string());

                        // Add tags for specific types of diagnostics
                        if message.contains("should be removed") || message.contains("Debug print") {
                            diagnostic.tags = Some(vec![DiagnosticTag::UNNECESSARY]);
                        }

                        diagnostics.push(diagnostic);
                    }
                }
            }
        }

        diagnostics
    }

    async fn check_syntax_errors(&self, content: &str, language: &str) -> CoreResult<Vec<Diagnostic>> {
        let mut diagnostics = Vec::new();

        // Create parser for the language
        let parser = match self.create_parser(language).await {
            Ok(parser) => parser,
            Err(e) => {
                error!("Failed to create parser for {}: {}", language, e);
                return Ok(diagnostics);
            }
        };

        // Parse the content
        match parser.parse(content, None).await {
            Ok(tree) => {
                // Check for error nodes in the syntax tree
                let root = tree.root_node();
                self.collect_syntax_errors(&*root, &mut diagnostics);
            }
            Err(e) => {
                // Parser failed completely
                diagnostics.push(Diagnostic {
                    range: Range::new(Position::new(0, 0), Position::new(0, 0)),
                    severity: Some(DiagnosticSeverity::ERROR),
                    code: Some(NumberOrString::String("parse_error".to_string())),
                    source: Some("CodeGraph-RT".to_string()),
                    message: format!("Parse error: {}", e),
                    related_information: None,
                    tags: None,
                    code_description: None,
                    data: None,
                });
            }
        }

        Ok(diagnostics)
    }

    fn collect_syntax_errors(&self, node: &dyn codegraph_core::SyntaxNode, diagnostics: &mut Vec<Diagnostic>) {
        if node.kind() == "ERROR" {
            let start_pos = node.start_position();
            let end_pos = node.end_position();
            
            diagnostics.push(Diagnostic {
                range: Range::new(
                    Position::new(start_pos.row, start_pos.column),
                    Position::new(end_pos.row, end_pos.column),
                ),
                severity: Some(DiagnosticSeverity::ERROR),
                code: Some(NumberOrString::String("syntax_error".to_string())),
                source: Some("codegraph-syntax".to_string()),
                message: self.get_specific_syntax_error_message(node),
                related_information: None,
                tags: None,
                code_description: None,
                data: None,
            });
        }

        // Check for error nodes that might indicate syntax issues
        if node.kind() == "ERROR" {
            let start_pos = node.start_position();
            let end_pos = node.end_position();

            diagnostics.push(Diagnostic {
                range: Range::new(
                    Position::new(start_pos.row, start_pos.column),
                    Position::new(end_pos.row, end_pos.column),
                ),
                severity: Some(DiagnosticSeverity::ERROR),
                code: Some(NumberOrString::String("syntax_error".to_string())),
                source: Some("codegraph-syntax".to_string()),
                message: format!("Syntax error in {}", node.kind()),
                related_information: None,
                tags: None,
                code_description: None,
                data: None,
            });
        }

        // Recursively check children
        for child in node.children() {
            self.collect_syntax_errors(&*child, diagnostics);
        }
    }

    /// Get more specific error messages based on the syntax error context
    fn get_specific_syntax_error_message(&self, node: &dyn codegraph_core::SyntaxNode) -> String {
        let node_text = node.text();
        let node_kind = node.kind();

        match node_kind {
            "function_definition" => "Invalid function definition syntax".to_string(),
            "class_definition" => "Invalid class definition syntax".to_string(),
            "if_statement" => "Invalid if statement syntax".to_string(),
            "for_statement" => "Invalid for loop syntax".to_string(),
            "while_statement" => "Invalid while loop syntax".to_string(),
            "import_statement" => "Invalid import statement syntax".to_string(),
            _ => {
                if node_text.is_empty() {
                    "Unexpected syntax error".to_string()
                } else {
                    format!("Syntax error near '{}'", node_text.trim())
                }
            }
        }
    }

    async fn check_semantic_issues(&self, content: &str, language: &str, _uri: &Url) -> CoreResult<Vec<Diagnostic>> {
        let mut diagnostics = Vec::new();

        // Get the graph system
        let graph_system = self.graph_system.read().await;
        let _graph_system = match graph_system.as_ref() {
            Some(system) => system,
            None => {
                debug!("Graph system not available for semantic analysis");
                return Ok(diagnostics);
            }
        };

        // Check for common semantic issues based on language
        match language {
            "python" => {
                diagnostics.extend(self.check_python_semantic_issues(content));
            }
            "javascript" | "typescript" => {
                diagnostics.extend(self.check_js_semantic_issues(content));
            }
            "rust" => {
                diagnostics.extend(self.check_rust_semantic_issues(content));
            }
            _ => {}
        }

        // TODO: Use graph system for more advanced semantic analysis
        // This would include:
        // - Cross-file undefined variable references
        // - Type mismatches using type inference
        // - Unused imports detection
        // - Dead code detection
        // - Circular dependencies

        Ok(diagnostics)
    }

    /// Check Python-specific semantic issues
    fn check_python_semantic_issues(&self, content: &str) -> Vec<Diagnostic> {
        let mut diagnostics = Vec::new();

        for (line_num, line) in content.lines().enumerate() {
            let trimmed = line.trim();

            // Check for undefined variables (simple heuristic)
            if let Some(captures) = Regex::new(r"(\w+)\s*=").unwrap().captures(trimmed) {
                if let Some(var_name) = captures.get(1) {
                    // Check if variable is used before definition (simplified)
                    let var_str = var_name.as_str();
                    let lines_before: Vec<&str> = content.lines().take(line_num).collect();
                    let used_before = lines_before.iter().any(|l| l.contains(var_str) && !l.trim().starts_with('#'));

                    if used_before && !self.is_builtin_python(var_str) {
                        let start_col = var_name.start();
                        let end_col = var_name.end();
                        let range = Range::new(
                            Position::new(line_num as u32, start_col as u32),
                            Position::new(line_num as u32, end_col as u32),
                        );

                        let mut diagnostic = Diagnostic::new_simple(range, format!("Variable '{}' may be used before assignment", var_str));
                        diagnostic.severity = Some(DiagnosticSeverity::WARNING);
                        diagnostic.source = Some("codegraph-semantic".to_string());
                        diagnostics.push(diagnostic);
                    }
                }
            }

            // Check for unused imports (simplified)
            if trimmed.starts_with("import ") || trimmed.starts_with("from ") {
                if let Some(captures) = Regex::new(r"import\s+(\w+)").unwrap().captures(trimmed) {
                    if let Some(module_name) = captures.get(1) {
                        let module_str = module_name.as_str();
                        let is_used = content.lines().skip(line_num + 1).any(|l| l.contains(module_str));

                        if !is_used {
                            let range = Range::new(
                                Position::new(line_num as u32, 0),
                                Position::new(line_num as u32, line.len() as u32),
                            );

                            let mut diagnostic = Diagnostic::new_simple(range, format!("Unused import '{}'", module_str));
                            diagnostic.severity = Some(DiagnosticSeverity::HINT);
                            diagnostic.source = Some("codegraph-semantic".to_string());
                            diagnostic.tags = Some(vec![DiagnosticTag::UNNECESSARY]);
                            diagnostics.push(diagnostic);
                        }
                    }
                }
            }
        }

        diagnostics
    }

    /// Check JavaScript/TypeScript-specific semantic issues
    fn check_js_semantic_issues(&self, content: &str) -> Vec<Diagnostic> {
        let mut diagnostics = Vec::new();

        for (line_num, line) in content.lines().enumerate() {
            let trimmed = line.trim();

            // Check for var usage (should use let/const)
            if trimmed.starts_with("var ") {
                let range = Range::new(
                    Position::new(line_num as u32, 0),
                    Position::new(line_num as u32, 3),
                );

                let mut diagnostic = Diagnostic::new_simple(range, "Use 'let' or 'const' instead of 'var'".to_string());
                diagnostic.severity = Some(DiagnosticSeverity::WARNING);
                diagnostic.source = Some("codegraph-semantic".to_string());
                diagnostics.push(diagnostic);
            }

            // Check for == usage (should use ===)
            if trimmed.contains("==") && !trimmed.contains("===") && !trimmed.contains("!==") {
                if let Some(pos) = line.find("==") {
                    let range = Range::new(
                        Position::new(line_num as u32, pos as u32),
                        Position::new(line_num as u32, (pos + 2) as u32),
                    );

                    let mut diagnostic = Diagnostic::new_simple(range, "Use strict equality (===) instead of ==".to_string());
                    diagnostic.severity = Some(DiagnosticSeverity::WARNING);
                    diagnostic.source = Some("codegraph-semantic".to_string());
                    diagnostics.push(diagnostic);
                }
            }
        }

        diagnostics
    }

    /// Check Rust-specific semantic issues
    fn check_rust_semantic_issues(&self, content: &str) -> Vec<Diagnostic> {
        let mut diagnostics = Vec::new();

        for (line_num, line) in content.lines().enumerate() {
            let trimmed = line.trim();

            // Check for unused variables (starting with underscore)
            if let Some(captures) = Regex::new(r"let\s+(\w+)").unwrap().captures(trimmed) {
                if let Some(var_name) = captures.get(1) {
                    let var_str = var_name.as_str();
                    if !var_str.starts_with('_') {
                        let is_used = content.lines().skip(line_num + 1).any(|l| l.contains(var_str));

                        if !is_used {
                            let start_col = var_name.start();
                            let end_col = var_name.end();
                            let range = Range::new(
                                Position::new(line_num as u32, start_col as u32),
                                Position::new(line_num as u32, end_col as u32),
                            );

                            let mut diagnostic = Diagnostic::new_simple(range, format!("Unused variable '{}'. Consider prefixing with '_'", var_str));
                            diagnostic.severity = Some(DiagnosticSeverity::WARNING);
                            diagnostic.source = Some("codegraph-semantic".to_string());
                            diagnostic.tags = Some(vec![DiagnosticTag::UNNECESSARY]);
                            diagnostics.push(diagnostic);
                        }
                    }
                }
            }
        }

        diagnostics
    }

    /// Check if a name is a Python builtin
    fn is_builtin_python(&self, name: &str) -> bool {
        matches!(name, "print" | "len" | "str" | "int" | "float" | "list" | "dict" | "set" | "tuple" | "range" | "enumerate" | "zip" | "map" | "filter" | "sum" | "max" | "min" | "abs" | "round" | "sorted" | "reversed")
    }

    async fn check_code_quality(&self, content: &str, language: &str) -> CoreResult<Vec<Diagnostic>> {
        let mut diagnostics = Vec::new();

        // Check for common code quality issues
        self.check_line_length(content, &mut diagnostics);
        self.check_complexity(content, language, &mut diagnostics);
        self.check_naming_conventions(content, language, &mut diagnostics);
        self.check_documentation(content, language, &mut diagnostics);
        self.check_performance_issues(content, language, &mut diagnostics);

        Ok(diagnostics)
    }

    fn check_line_length(&self, content: &str, diagnostics: &mut Vec<Diagnostic>) {
        const MAX_LINE_LENGTH: usize = 120;

        for (line_num, line) in content.lines().enumerate() {
            if line.len() > MAX_LINE_LENGTH {
                diagnostics.push(Diagnostic {
                    range: Range::new(
                        Position::new(line_num as u32, MAX_LINE_LENGTH as u32),
                        Position::new(line_num as u32, line.len() as u32),
                    ),
                    severity: Some(DiagnosticSeverity::WARNING),
                    code: Some(NumberOrString::String("line_too_long".to_string())),
                    source: Some("codegraph-quality".to_string()),
                    message: format!("Line too long ({} > {})", line.len(), MAX_LINE_LENGTH),
                    related_information: None,
                    tags: None,
                    code_description: None,
                    data: None,
                });
            }
        }
    }

    fn check_complexity(&self, content: &str, language: &str, diagnostics: &mut Vec<Diagnostic>) {
        // Simple complexity check based on nesting level
        let mut max_nesting = 0;
        let mut current_nesting = 0;
        let mut line_with_max_nesting = 0;

        for (line_num, line) in content.lines().enumerate() {
            let trimmed = line.trim();
            
            // Count opening braces/blocks
            let opens = match language {
                "python" => trimmed.matches(':').count(),
                _ => trimmed.matches('{').count(),
            };
            
            // Count closing braces/blocks
            let closes = match language {
                "python" => 0, // Python uses indentation
                _ => trimmed.matches('}').count(),
            };

            current_nesting += opens;
            current_nesting = current_nesting.saturating_sub(closes);

            if current_nesting > max_nesting {
                max_nesting = current_nesting;
                line_with_max_nesting = line_num;
            }
        }

        if max_nesting > 5 {
            diagnostics.push(Diagnostic {
                range: Range::new(
                    Position::new(line_with_max_nesting as u32, 0),
                    Position::new(line_with_max_nesting as u32, 0),
                ),
                severity: Some(DiagnosticSeverity::INFORMATION),
                code: Some(NumberOrString::String("high_complexity".to_string())),
                source: Some("CodeGraph-RT".to_string()),
                message: format!("High complexity detected (nesting level: {})", max_nesting),
                related_information: None,
                tags: None,
                code_description: None,
                data: None,
            });
        }
    }

    fn check_naming_conventions(&self, content: &str, language: &str, diagnostics: &mut Vec<Diagnostic>) {
        // Simple naming convention checks
        for (line_num, line) in content.lines().enumerate() {
            match language {
                "python" => {
                    // Check for camelCase in Python (should be snake_case)
                    if line.contains("def ") && line.contains(char::is_uppercase) {
                        diagnostics.push(Diagnostic {
                            range: Range::new(
                                Position::new(line_num as u32, 0),
                                Position::new(line_num as u32, line.len() as u32),
                            ),
                            severity: Some(DiagnosticSeverity::INFORMATION),
                            code: Some(NumberOrString::String("naming_convention".to_string())),
                            source: Some("CodeGraph-RT".to_string()),
                            message: "Consider using snake_case for function names in Python".to_string(),
                            related_information: None,
                            tags: None,
                            code_description: None,
                            data: None,
                        });
                    }
                }
                "javascript" | "typescript" => {
                    // Check for snake_case in JS/TS (should be camelCase)
                    if line.contains("function ") && line.contains('_') {
                        diagnostics.push(Diagnostic {
                            range: Range::new(
                                Position::new(line_num as u32, 0),
                                Position::new(line_num as u32, line.len() as u32),
                            ),
                            severity: Some(DiagnosticSeverity::INFORMATION),
                            code: Some(NumberOrString::String("naming_convention".to_string())),
                            source: Some("CodeGraph-RT".to_string()),
                            message: "Consider using camelCase for function names in JavaScript/TypeScript".to_string(),
                            related_information: None,
                            tags: None,
                            code_description: None,
                            data: None,
                        });
                    }
                }
                _ => {}
            }
        }
    }

    async fn create_parser(&self, language: &str) -> CoreResult<Box<dyn Parser>> {
        match language {
            "python" => Ok(Box::new(TreeSitterParser::python()?)),
            "javascript" => Ok(Box::new(TreeSitterParser::javascript()?)),
            "typescript" => Ok(Box::new(TreeSitterParser::typescript()?)),
            "rust" => Ok(Box::new(TreeSitterParser::rust()?)),
            _ => Err(codegraph_core::CodeGraphError::parse_error(format!("Unsupported language: {}", language))),
        }
    }

    /// Check for missing documentation
    fn check_documentation(&self, content: &str, language: &str, diagnostics: &mut Vec<Diagnostic>) {
        for (line_num, line) in content.lines().enumerate() {
            let trimmed = line.trim();

            // Check for functions without documentation
            let is_function = match language {
                "python" => trimmed.starts_with("def ") && trimmed.contains('('),
                "javascript" | "typescript" => trimmed.starts_with("function ") ||
                    (trimmed.starts_with("const ") && trimmed.contains("=>")),
                "rust" => trimmed.starts_with("pub fn ") || trimmed.starts_with("fn "),
                _ => false,
            };

            if is_function {
                // Check if there's documentation above this function
                let has_doc = if line_num > 0 {
                    let prev_lines: Vec<&str> = content.lines().take(line_num).collect();
                    let mut has_documentation = false;

                    for prev_line in prev_lines.iter().rev().take(3) {
                        let prev_trimmed = prev_line.trim();
                        if prev_trimmed.is_empty() {
                            continue;
                        }

                        let is_doc = match language {
                            "python" => prev_trimmed.starts_with("\"\"\"") || prev_trimmed.starts_with('#'),
                            "javascript" | "typescript" => prev_trimmed.starts_with("/**") || prev_trimmed.starts_with("//"),
                            "rust" => prev_trimmed.starts_with("///") || prev_trimmed.starts_with("//!"),
                            _ => false,
                        };

                        if is_doc {
                            has_documentation = true;
                            break;
                        } else {
                            break; // Non-empty, non-doc line found
                        }
                    }

                    has_documentation
                } else {
                    false
                };

                if !has_doc {
                    let range = Range::new(
                        Position::new(line_num as u32, 0),
                        Position::new(line_num as u32, line.len() as u32),
                    );

                    let mut diagnostic = Diagnostic::new_simple(range, "Function should have documentation".to_string());
                    diagnostic.severity = Some(DiagnosticSeverity::INFORMATION);
                    diagnostic.source = Some("codegraph-quality".to_string());
                    diagnostics.push(diagnostic);
                }
            }
        }
    }

    /// Check for potential performance issues
    fn check_performance_issues(&self, content: &str, language: &str, diagnostics: &mut Vec<Diagnostic>) {
        for (line_num, line) in content.lines().enumerate() {
            let trimmed = line.trim();

            match language {
                "python" => {
                    // Check for inefficient string concatenation in loops
                    if (trimmed.contains("for ") || trimmed.contains("while ")) &&
                       content.lines().skip(line_num + 1).take(10).any(|l| l.contains("+=") && l.contains("str")) {
                        let range = Range::new(
                            Position::new(line_num as u32, 0),
                            Position::new(line_num as u32, line.len() as u32),
                        );

                        let mut diagnostic = Diagnostic::new_simple(range, "Consider using join() for string concatenation in loops".to_string());
                        diagnostic.severity = Some(DiagnosticSeverity::INFORMATION);
                        diagnostic.source = Some("codegraph-performance".to_string());
                        diagnostics.push(diagnostic);
                    }
                }
                "javascript" | "typescript" => {
                    // Check for inefficient array operations
                    if trimmed.contains(".forEach(") && trimmed.contains("push(") {
                        let range = Range::new(
                            Position::new(line_num as u32, 0),
                            Position::new(line_num as u32, line.len() as u32),
                        );

                        let mut diagnostic = Diagnostic::new_simple(range, "Consider using map() instead of forEach() with push()".to_string());
                        diagnostic.severity = Some(DiagnosticSeverity::INFORMATION);
                        diagnostic.source = Some("codegraph-performance".to_string());
                        diagnostics.push(diagnostic);
                    }
                }
                "rust" => {
                    // Check for unnecessary clones
                    if trimmed.contains(".clone()") && !trimmed.contains("// clone needed") {
                        if let Some(pos) = line.find(".clone()") {
                            let range = Range::new(
                                Position::new(line_num as u32, pos as u32),
                                Position::new(line_num as u32, (pos + 8) as u32),
                            );

                            let mut diagnostic = Diagnostic::new_simple(range, "Consider if clone() is necessary here".to_string());
                            diagnostic.severity = Some(DiagnosticSeverity::INFORMATION);
                            diagnostic.source = Some("codegraph-performance".to_string());
                            diagnostics.push(diagnostic);
                        }
                    }
                }
                _ => {}
            }
        }
    }
}
